package cameraUI;

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.Random;

import javax.imageio.ImageIO;

import featureExtraction.TokenCollection;
import featureExtraction.TokenDetection;
import featureExtraction.TokenRaw;

import projectUtils.ByteUtil;
import projectUtils.ImageArrayUtil;
import projectUtils.ImageLoader;
import aNN.NeuralNetwork;
import annTrain.TrainerHelper;

public class DigitRecognition {
	
	NeuralNetwork cnn;
	BufferedImage resultImage;
	
	public DigitRecognition()
	{
		cnn = new NeuralNetwork();
		cnn.Import(System.getProperty("user.dir") + "\\" + "CNN_Handwritten_Digits.txt");
	}
	
	public int Recognize(BufferedImage image)
	{

		TokenDetection tokenDetector = new TokenDetection();
		TokenCollection tokenCollection = tokenDetector.SegmentImageTokens(image);
		double maxSize = 0;
		TokenRaw digitToken = null;
		for (TokenRaw token : tokenCollection.Tokens)
		{
			if ((token.X1 - token.X0) * (token.Y1 - token.Y0) > maxSize)
			{
				digitToken = token;
				maxSize = (token.X1 - token.X0) * (token.Y1 - token.Y0);
			}
		}
		
		if (digitToken == null)
			return -1;

		image = ImageArrayUtil.CreateSubImage(image, digitToken.X0, digitToken.X1, digitToken.Y0, digitToken.Y1);
		byte[][] se = new byte[3][3];
		for (int k = 0; k < 3; k++)
		{
			for (int l = 0; l < 3; l++)
				se[k][l] = 1;
		}
		for (int k = 0; k < 3; k++)
		{
			image = ImageArrayUtil.PadImage(image, 2, 2);
			image =  ImageArrayUtil.DilateImage(image, se);
		}
		image = ImageArrayUtil.PadImage(image, (int)(image.getWidth() * 0.4), (int)(image.getHeight() * 0.25));

		
//		resultImage = image;
		
		byte[][] imageArray;
		imageArray = ImageArrayUtil.ShiftBasedOnCenterOfMass(ImageArrayUtil.NormalizeArrayValue(ImageArrayUtil.ImageToArray(ImageArrayUtil.CreateResizedCopy(image, 29, 29))));
		double[] input = new double[imageArray.length * imageArray[0].length];
		for (int i = 0; i < imageArray.length; i++)
		{
			for (int j = 0; j < imageArray[i].length; j++)
			{
				input[i * imageArray[i].length + j] = /*Math.round*/((double)ByteUtil.ByteToInt(imageArray[i][j]) / 255.0 * 4.0) / 4.0 * 2.0 - 1.0;

				cnn.InputLayer.Neurons.get(i * 29 + j).setValues(input[i * imageArray[i].length + j], input[i * imageArray[i].length + j]);
			}
		}
		
//		File outputFile = new File(System.getProperty("user.dir") + "\\temp\\" + new Random().nextLong() + ".png");
//		//ImageIO.write(originalImage, "png", outputFile);
//		try {
//			ImageIO.write(ImageArrayUtil.ArrayToImage(imageArray), "png", outputFile);
//		} catch (IOException e) {
//			// TODO Auto-generated catch block
//			e.printStackTrace();
//		}
		resultImage = ImageArrayUtil.ArrayToImage(imageArray);
		
		cnn.Calculate();
		double[] results = new double[10];
		for (int i = 0; i < 10; i++)
			results[i] = cnn.OutputLayer.Neurons.get(i).getOuput();
		TrainerHelper helper = new TrainerHelper();
		int result = helper.GetCalculatedResult(results);
		System.out.println(result);
//		for (int i = 0; i < 10; i++)
//			System.out.println(results[i]);
		return result;
	}
}
